﻿using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using AForge.Video;
using AForge.Video.DirectShow;
using Ini.Net;
using Newtonsoft.Json;
using AForge.Imaging.Filters;

namespace FaceIdentifier
{
    class VideoDeviceSource
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(VideoDeviceSource));
        private readonly object sync = new object();
        private IVideoSource _captureDevice;
        private IniFile config = new IniFile("相机配置.ini");
        private Bitmap currentFrame;
        public delegate void FPS(object sender, Bitmap bitmap);
        public event FPS _fps;
        private Pen pen = new Pen(new SolidBrush(Color.Yellow),5f);

        private bool requestStop = false;

        public void Start() {
            if(_captureDevice == null)
            {
                requestStop = false;
                if(File.Exists(Path.Combine("Resources", "720p.avi")))
                {
                    //使用本地Resources目录下的720p.avi文件识别测试
                    _captureDevice = GetFileVideoSource();
                }else
                {
                    //使用USB摄像机识别
                    _captureDevice = GetCaptureDevice();
                }
                
                
                _captureDevice.NewFrame += _captureDevice_NewFrame;
                _captureDevice.PlayingFinished += _captureDevice_Finished;
            }

            _captureDevice.Start();
            log.Info("开始播放");
        }

        private void _captureDevice_Finished(object sender, ReasonToFinishPlaying reason)
        {
            log.Info("播放结束");
            Stop();
            Start();
        }

        public void Stop()
        {
            if (_captureDevice == null) return;
            requestStop = true;
            _captureDevice.NewFrame -= _captureDevice_NewFrame;
            _captureDevice.Stop();
            _captureDevice = null;
            log.Info("停止播放");
        }

        private void _captureDevice_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            if (requestStop) return;
            Bitmap newFrame = (Bitmap)eventArgs.Frame.Clone();
            //如果使用视频文件请注释下面的这行代码，表示不对图像进行水平翻转
            newFrame.RotateFlip(RotateFlipType.Rotate180FlipY);
            lock (sync)
            {
                if (currentFrame != null)
                {
                    currentFrame.Dispose();
                    currentFrame = null;
                }
                currentFrame = newFrame;
                _fps.Invoke(sender, newFrame);
            }
        }

        public Bitmap GetCurrentFrame()
        {
            if (requestStop) return null;
            lock (sync)
            {
                return (currentFrame == null || currentFrame.Width == 0 || currentFrame.Height == 0) ? null : AForge.Imaging.Image.Clone(currentFrame);
            }
        }



        private VideoCaptureDevice GetCaptureDevice()
        {
            FilterInfoCollection filters = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            if(filters.Count == 0)
            {
                return null;
            }

            Size maxSize = new Size(0, 0);

            var videoCaptureDevice = new VideoCaptureDevice(filters[0].MonikerString);
            var capabilities = videoCaptureDevice.VideoCapabilities;
            foreach (var item in capabilities)
            {
                if(item.FrameSize.Width > maxSize.Width)
                {
                    maxSize = item.FrameSize;
                    videoCaptureDevice.VideoResolution = item;
                }
            }

            return videoCaptureDevice;
        }

        private FileVideoSource GetFileVideoSource()
        {
            return new FileVideoSource(Path.Combine("Resources","720p.avi"));
        }


        public void PaintToPictureBox(PictureBox pictureBox1, Graphics g)
        {
            if (requestStop) return;
            using(Bitmap bitmap = GetCurrentFrame())
            {
                if (currentFrame == null)
                {
                    return;
                }

                int w = pictureBox1.Width;
                int h = pictureBox1.Height;

                Rectangle rect1 = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
                Rectangle rect2 = new Rectangle(0, 0, w, h);
                g.DrawImage(bitmap, rect2,rect1, GraphicsUnit.Pixel);

                int point = 30;
                int point_width = 80;
                g.DrawLines(pen, new PointF[] { new PointF(point_width, point) ,new PointF(point, point), new PointF(point, point_width) });
                g.DrawLines(pen, new PointF[] { new PointF(w - point_width, point), new PointF(w -point, point), new PointF(w - point, point_width) });
                g.DrawLines(pen, new PointF[] { new PointF(point,h-point_width), new PointF(point, h-point), new PointF(point_width, h-point) });
                g.DrawLines(pen, new PointF[] { new PointF(w-point_width,h-point), new PointF(w-point, h-point), new PointF(w - point, h - point_width) });
            }
        }

        internal Bitmap GetCurrentCropFrame()
        {
            using(var bitmap = GetCurrentFrame())
            {
                Bitmap result = new Bitmap(bitmap.Width / 4, bitmap.Height / 4);
                using(Graphics g = Graphics.FromImage(result))
                {
                    g.DrawImage(bitmap, new Rectangle(0, 0, result.Width, result.Height), new Rectangle(0, 0, bitmap.Width, bitmap.Height), GraphicsUnit.Pixel);
                }
                return result;
            }
        }
    }
}
